#include "sessionfriendarea.h"

#include "debug.h"
#include "model/data.h"
#include "mainwidget.h"
#include "model/datacenter.h"

/********************************************************************************************************************************
 * 中间窗口的会话 中间滚动区域
 ********************************************************************************************************************************/
SessionFriendArea::SessionFriendArea(QWidget *parent)
    : QScrollArea{parent}
{
    //1.设置了这个属性，才能开启滚动效果
    this->setWidgetResizable(true);
    //2.设置滚动条的样式
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 4px; background-color: rgb(46, 46, 46);}");
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0px; }");
    this->setStyleSheet("QWidget { border: none;}");

    container = new QWidget();
    container->setFixedWidth(325);
    this->setWidget(container); //告诉滚动区，要监视当前的Widget

    //给Widget添加布局管理器
    vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0,0,0,0);
    vlayout->setAlignment(Qt::AlignTop);
    container->setLayout(vlayout);

#ifdef TEST_UI
    QIcon image(":/resource/lion.png");
    for(int i = 0; i < 50; ++i)
    {
        this->addItem(SESSIONITEM_TYPE,QString::number(i+1),image,QString("张三") + QString::number(i+1),QString("这是一条消息") + QString::number(i+1));
    }
#endif
}

//清除区域中所有的会话列表
void SessionFriendArea::clear()
{
    QLayout* layout = container->layout();
    for(int i = layout->count() -1; i >= 0; --i)
    {
        QLayoutItem* item = layout->takeAt(i);  //移除
        //由于布局中的对象全部都是new出来的，所以别忘记释放
        if(item->widget())
        {
            delete item->widget();
        }
    }
}

// 向区域中添加会话列表
// 此时这个函数添加的就不是 SessionFriendItem 了, 而是 SessionFriendItem 的子类.
// SessionItem, FriendItem, ApplyItem 其中的一个.
void SessionFriendArea::addItem(ItemType itemType,const QString id,const QIcon &avatar, const QString name, const QString text)
{
    SessionFriendItem* item= nullptr;
    switch(itemType)
    {
    case SESSIONITEM_TYPE:
        item = new SessionItem(this,id,avatar,name,text);
        break;
    case FRIENDITEM_TYPE:
        item = new FriendItem(this,id,avatar,name,text);
        break;
    case APPLYITEM_TYPE:
        item = new ApplyItem(this,id,avatar,name);
        break;
    default:
        LOG() << "itemType 错误";
        break;
    }
    container->layout()->addWidget(item);
}

void SessionFriendArea::clickItem(int index)
{
    LOG() << "index下标：" << index;
    LOG() << "会话列表中共计:" << container->layout()->count();
    if(index < 0 || index >= container->layout()->count())
    {
        LOG() << "点击下标元素超出范围！ index = " << index;
        return;
    }

    QLayoutItem *layoutItem = container->layout()->takeAt(index);
    if(layoutItem == nullptr || layoutItem->widget() == nullptr)
    {
        LOG() << "指定元素不存在";
        return;
    }

    //将指定的元素选中
    SessionFriendItem *item = dynamic_cast<SessionFriendItem*>(layoutItem->widget());
    item->select();
}






/********************************************************************************************************************************
 * 滚动区域中的Item
 ********************************************************************************************************************************/

SessionFriendItem::SessionFriendItem(QWidget *owner, const QIcon &avatar, const QString name, const QString lastMessage)
    :owner(owner)
    ,isSelect(false)
{
    this->setFixedHeight(70);
    this->setStyleSheet("QWidget {background-color: rgb(231,231,231);}");

    //创建网格布局
    QGridLayout* glayout = new QGridLayout();
    glayout->setSpacing(8);
    glayout->setContentsMargins(10,0,0,0);
    this->setLayout(glayout);

    //创建头像
    avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(58,58);
    avatarBtn->setIconSize(QSize(58,58));
    avatarBtn->setIcon(avatar);
    avatarBtn->setStyleSheet("QPushButton {border: none};");
    avatarBtn->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

    //创建网名
    nameLabel = new QLabel();
    nameLabel->setText(name);
    nameLabel->setFixedHeight(25);
    nameLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
    nameLabel->setStyleSheet("QLabel {font-size:18px; font-weight:380;}");
    nameLabel->setAlignment(Qt::AlignBottom);

    //创建最后一条消息
    messageLabel = new QLabel();
    messageLabel->setText(lastMessage);
    messageLabel->setFixedHeight(25);
    messageLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
    messageLabel->setStyleSheet("QLabel {font-size:12px;}");

    //添加至布局中
    // 头像处于 0, 0 位置, 占据 2 行, 占据 2 列
    glayout->addWidget(avatarBtn,0,0,2,2);
    // 名字处于 0, 2 位置, 占据 1 行, 占据 1 列
    glayout->addWidget(nameLabel,0,2,1,8);
    glayout->addWidget(messageLabel,1,2,1,8);

    //关连信号槽，点击消息中的头像，弹出用户详细信息（在一条MessageItem产生时）
}

//SessionFriendItem的背景色，需要特殊设置
void SessionFriendItem::paintEvent(QPaintEvent *event)
{
    (void) event;
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void SessionFriendItem::mousePressEvent(QMouseEvent *event)
{
    (void) event;
    //拿到所有兄弟元素
    this->select();
    // this->active();
}

void SessionFriendItem::enterEvent(QEnterEvent *event)
{
    (void) event;
    // 当前这个 item 是选中状态, 则背景色不受到该逻辑影响
    if (this->isSelect) {
        return;
    }
    // 设置一个更深的颜色
    this->setStyleSheet("QWidget { background-color: rgb(220, 220, 220);}");
}

void SessionFriendItem::leaveEvent(QEvent *event)
{
    (void) event;
    // 当前这个 item 是选中状态, 则背景色不受到该逻辑影响
    if (this->isSelect) {
        return;
    }
    // 还原背景色
    this->setStyleSheet("QWidget { background-color: rgb(231, 231, 231);}");
}

void SessionFriendItem::select()
{
    const QObjectList children = this->parent()->children();
    for(QObject* child : children)
    {
        if (!child->isWidgetType()) {
            // 判定是否是 widget.
            continue;
        }
        // 确实是 widget, 就把这里的child 强转成 SessionFriendItem
        SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(child);
        if(item->isSelect)
        {
            item->isSelect = false;
            item->setStyleSheet("QWidget { background-color: rgb(231, 231, 231); }");
        }
    }
    // 此处不仅仅要设置当前 item 背景色, 也要还原其他元素的背景色.
    this->setStyleSheet("QWidget { background-color: rgb(210, 210, 210); }");
    this->isSelect = true;

    this->active();
}

void SessionFriendItem::active()
{
    //父类的active，此处不实现，子类去实现
}

/**********************************************************************************************
 * 滚动区域中的会话列表元素
 **********************************************************************************************/
SessionItem::SessionItem(QWidget *owner,  const QString &chatSessionId, const QIcon &avatar, const QString name, const QString lastMessage)
    :SessionFriendItem(owner,avatar,name,lastMessage)
    ,chatSessionID(chatSessionId)
    ,text(lastMessage)
{
    //处理最后一个消息更新的信号
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    connect(dataCenter,&model::DataCenter::updateLastMessage,this,&SessionItem::updateLastMessage);

    //显示出未读消息数目，为了支持客户端重启后，未读消息仍然显示
    int unRead = dataCenter->getUnread(chatSessionId);
    if(unRead > 0)
    {
        //存在未读消息
        messageLabel->setText(QString("[未读%1条]").arg(unRead) + text);
    }
}

void SessionItem::active()
{
    LOG() << "点击 SessionItem 触发的逻辑! chatSessionId=" << chatSessionID;
    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->loadRecentMessage(chatSessionID);

    //清空未读消息数目，并且更新显示
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->clearUnread(chatSessionID);

    //将前面的未读干掉
    this->messageLabel->setText(text);
}

void SessionItem::updateLastMessage(const QString &chatSessionId)
{
    //注意，所有的SessionItem都会收到该信号
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(this->chatSessionID != chatSessionId)
    {
        //不是对应的会话，不更新最后一个消息
        return;
    }

    QList<model::MessageInfo>* messageList  = dataCenter->getRecentMessageList(chatSessionId);
    if(messageList == nullptr || messageList->size() == 0)
    {
        return;
    }
    const MessageInfo& lastMessage = messageList->back();
    // 3. 明确显示的文本内容
    //    由于消息有四种类型.
    //    文本消息, 直接显示消息的内容; 图片消息, 直接显示 "[图片]"; 文件消息, 直接显示 "[文件]"; 语音消息, 直接显示 "[语音]"
    if (lastMessage.messageType == model::MessageType::TEXT_TYPE) {
        text = lastMessage.content;
    } else if (lastMessage.messageType == model::MessageType::IMAGE_TYPE) {
        text = "[图片]";
    } else if (lastMessage.messageType == model::MessageType::FILE_TYPE) {
        text = "[文件]";
    } else if (lastMessage.messageType == model::MessageType::SPEECH_TYPE) {
        text = "[语音]";
    } else {
        LOG() << "错误的消息类型!";
        return;
    }
    //4.把这个内容，显示在界面上
    if(chatSessionId == dataCenter->getCurrentSessionId())
    {
        this->messageLabel->setText(text);
    }
    else
    {
        int unRead = dataCenter->getUnread(chatSessionId);
        if(unRead > 0)
        {
            messageLabel->setText(QString("[未读%1条]").arg(unRead) + text);
        }
    }
}


/**********************************************************************************************
 * 滚动区域中的好友列表元素
 **********************************************************************************************/
FriendItem::FriendItem(QWidget *owner, const QString &userID, const QIcon &avatar, const QString name, const QString description)
    :SessionFriendItem(owner,avatar,name,description)
    ,userID(userID)
{
    // LOG() << "FriendItem 被创建";
}

void FriendItem::active()
{
    //friendltem:点击之后，要切换到会话列表，并且选中对应的会话。
    LOG() << "点击 FriendItem 触发的逻辑! userId=" << userID;
    //切换到会话列表
    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->switchSession(userID);
}


/**********************************************************************************************
 * 滚动区域中的好友申请列表元素
 **********************************************************************************************/
ApplyItem::ApplyItem(QWidget *owner, const QString &applyID, const QIcon &avatar, const QString name)
    :SessionFriendItem(owner,avatar,name,"")
    ,applyID(applyID)
{
     // LOG() << "applyItem 被创建";
    //1.移除父类中的messageLabel
    QGridLayout* glayout = dynamic_cast<QGridLayout*>(this->layout());
    glayout->removeWidget(messageLabel);
    delete messageLabel;

   //2.创建两个按钮出来
    QPushButton* receiveBtn = new QPushButton("接受");
    QPushButton* rejectBtn = new QPushButton("拒绝");
    // 接受按钮：绿色系
    receiveBtn->setStyleSheet(
        "QPushButton{"
        "min-width: 80px;"
        "min-height:20px;"
        "background-color: rgb(71, 195, 101);"
        "border-radius: 6px;"
        "}"
        "QPushButton:hover{"
        "background-color: rgb(90, 210, 120);"   // 悬停时稍亮
        "}"
        "QPushButton:pressed{"
        "background-color: rgb(55, 170, 85);"    // 按下时稍暗
        "}"
        );

    // 拒绝按钮：红色系
    rejectBtn->setStyleSheet(
        "QPushButton{"
        "min-width: 80px;"
        "min-height:20px;"
        "background-color: rgb(247, 87, 84);"
        "border-radius: 6px;"
        "}"
        "QPushButton:hover{"
        "background-color: rgb(255, 110, 105);"
        "}"
        "QPushButton:pressed{"
        "background-color: rgb(225, 70, 65);"
        "}"
        );

    glayout->addWidget(receiveBtn,1,2,1,1);
    glayout->addWidget(rejectBtn,1,3,1,1);

    connect(receiveBtn,&QPushButton::clicked,this,&ApplyItem::agreeFriendApply);
    connect(rejectBtn,&QPushButton::clicked,this,&ApplyItem::rejectFriendApply);
}

void ApplyItem::active()
{
    //applyltem:点击之后，无事发生。主要逻辑是靠"同意"拒绝"按钮触发的
    LOG() << "点击 ApplyItem 触发的逻辑! applyID=" << applyID;
}

void ApplyItem::agreeFriendApply()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->agreeFriendApplyAsync(this->applyID);
}

void ApplyItem::rejectFriendApply()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->rejectFriendApplyAsync(this->applyID);
}
